﻿using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;

namespace PyNet
{
    public class clsBuffer_Build
    {
        public byte[] buffer;
        public ushort len = 0;

        public clsBuffer_Build()
        {
            buffer = new byte[0];
        }

        public void InsertDWord(int value)
        {
            int pos = Allocate(4);
            BitConverter.GetBytes(value).CopyTo(buffer, pos);
        }

        public void InsertWord(short value)
        {
            int pos = Allocate(2);
            BitConverter.GetBytes(value).CopyTo(buffer, pos);
        }

        public void InsertByte(byte value)
        {
            int pos = Allocate(1);
            buffer[pos] = value;
        }

        public void InsertByteArray(byte[] value)
        {
            for (int i = 0; i < value.Length; i++)
            {
                InsertByte(value[i]);
            }
        }

        public void InsertLong(long value)
        {
            int pos = Allocate(8);
            BitConverter.GetBytes(value).CopyTo(buffer, pos);
        }

        public void InsertCString(string str)
        {
            InsertCString(str, Encoding.ASCII);
        }

        public void InsertCString(string str, Encoding enc)
        {
            if (str != null)
            {
                int pos = Allocate(str.Length);
                enc.GetBytes(str).CopyTo(buffer, pos);
                InsertByte(0);
            }
        }

        public void InsertDwordString(string str)
        {
            InsertDwordString(str, 0);
        }

        public void InsertDwordString(string str, byte padding)
        {
            if (str.Length < 4)
            {
                int numNulls = 4 - str.Length;
                for (int i = 0; i < numNulls; i++)
                    InsertByte(padding);
            }
            byte[] bar = Encoding.ASCII.GetBytes(str);
            for (int i = bar.Length - 1; i >= 0; i--)
                InsertByte(bar[i]);
        }

        /// <summary>
        /// Allocates space into the buffer.
        /// </summary>
        /// <param name="amount">The amount of bytes to allocate.</param>
        /// <returns>The position in which to insert your data that we have allocated space for.</returns>
        public int Allocate(int amount)
        {
            byte[] temp = new byte[buffer.Length + amount];
            buffer.CopyTo(temp, 0);
            buffer = temp;
            len += (ushort)amount;
            return buffer.Length - amount;
        }

        /// <summary>
        /// Builds your buffer into a packet.
        /// </summary>
        /// <param name="ID">Battle.net ID of the packet.</param>
        /// <returns>The data to send.</returns>
        public byte[] Build(byte ID)
        {
            byte[] temp = new byte[buffer.Length + 4];
            temp[0] = 0xDD;
            temp[1] = ID;
            BitConverter.GetBytes((ushort)temp.Length).CopyTo(temp, 2);
            buffer.CopyTo(temp, 4);
            buffer = new byte[0];
            len = 0;
            return temp;
        }
    }

    public class clsBuffer_Debuild
    {
        public byte[] buffer;
        public byte pID;
        public ushort pLength;
        private int pos;

        public int GetDWord()
        {
            int temp = BitConverter.ToInt32(buffer, pos);
            pos += 4;
            return temp;
        }

        public long GetLong()
        {
            long temp = BitConverter.ToInt64(buffer, pos);
            pos += 8;
            return temp;
        }

        public byte GetByte()
        {
            byte temp = buffer[pos];
            pos += 1;
            return temp;
        }

        public byte[] GetBytes(int amount)
        {
            byte[] temp = new byte[amount];
            for (int i = 0; i < amount; i++)
            {
                temp[i] = GetByte();
            }
            return temp;
        }

        public short GetWord()
        {
            short temp = BitConverter.ToInt16(buffer, pos);
            pos += 2;
            return temp;
        }

        public string GetCString()
        {
            byte[] temp;
            int letters = 0;
            byte next = 1;
            int fpos = pos;
            while (next != 0 && fpos < buffer.Length)
            {
                letters += 1;
                next = buffer[fpos];
                fpos++;
            }
            letters -= 1;
            temp = new byte[letters];
            for (int i = 0; i < letters; i++)
            {
                temp[i] = buffer[pos + i];
            }
            pos += letters + 1;
            return Encoding.ASCII.GetString(temp);
        }

        public byte Unbuild(byte[] data)
        {
            byte ID = 0xDD;
            byte[] all;
            all = data;
            if (all[0] == 0xDD)
            {
                ID = all[1];
                pID = ID;
                pos = 0;
                pLength = (ushort)BitConverter.ToInt16(all, 2);
                pLength -= 4;
                buffer = new byte[all.Length - 4];
                for (int i = 4; i < all.Length; i++)
                {
                    buffer[i - 4] = all[i];
                }
            }
            else
            {
                return 0xDD;
            }

            return ID;
        }
    }
}

